﻿using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.IO;

namespace Birkelund.QueryStrings.Internals
{
    internal static class ArgumentValidation
    {
        /// <summary>
        /// Throws an <see cref="ArgumentNullException"/> if value is null.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="paramName">Name of the param.</param>
        internal static void ThrowIfNull(object value, string paramName)
        {
            if (paramName == null)
            {
                throw new ArgumentNullException("paramName");
            }

            if (value == null)
            {
                throw new ArgumentNullException(paramName);
            }
        }

        /// <summary>
        /// Throws an <see cref="ArgumentNullException"/> if value is null or empty.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="paramName">Name of the param.</param>
        internal static void ThrowIfNullOrEmpty(string value, string paramName)
        {
            ThrowIfNull(paramName, "paramName");

            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException(paramName);
            }
        }

        /// <summary>
        /// Throws an <see cref="ArgumentException"/> if value is longer than maxlength.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="maxLength">Length of the max.</param>
        /// <param name="paramName">Name of the param.</param>
        internal static void ThrowIfLonger(string value, int maxLength, string paramName)
        {
            ThrowIfNull(value, paramName);
            if (value.Length > maxLength)
            {
                throw new ArgumentException("Max allowed length: " + maxLength, paramName);
            }
        }

        /// <summary>
        /// Throws an <see cref="ArgumentException"/> if value does not match the regex.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="regex">The regex.</param>
        /// <param name="paramName">Name of the param.</param>
        internal static void ThrowIfNotMatch(string value, Regex regex, string paramName)
        {
            ThrowIfNull(regex, "regex");
            if (!regex.IsMatch(value))
            {
                throw new ArgumentException("Invalid string", paramName);
            }
        }

        /// <summary>
        /// Throws an <see cref="ArgumentException"/> if value and match are equal.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="match">The match.</param>
        /// <param name="paramName">Name of the param.</param>
        internal static void ThrowIfEqual(string value, string match, string paramName)
        {
            if (value == match)
            {
                throw new ArgumentException(string.Format("'{0}' is reservated and cannot be used", match), paramName);
            }
        }

        internal static void ThrowIfInvalidFileName(string fileName)
        {
            ThrowIfNullOrEmpty(fileName, "fileName");

            foreach (char c in fileName)
            {
                if (Path.GetInvalidFileNameChars().Contains(c))
                {
                    throw new ArgumentException("Invalid chars in file name");
                }
            }

            int numberOfPeriods = fileName.ToCharArray().Count(x => x == '.');
            if (numberOfPeriods != 1)
            {
                throw new ArgumentException("Filename must have one . (period)");
            }
        }

        internal static void ThrowIfInvalidDirectoryName(string directoryName)
        {
            ThrowIfNullOrEmpty(directoryName, "directoryName");

            foreach (char c in directoryName)
            {
                if (Path.GetInvalidPathChars().Contains(c))
                {
                    throw new ArgumentException("Invalid chars in directory name");
                }
            }
        }
    }
}
